package com.seari.test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.CacheStats;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.seari.bean.Employee;

/**
 * 
 * @author 
 *
 */
public class CacheMap {
	private static final Logger logger = LoggerFactory.getLogger(CacheMap.class);

	/**
	 * 使用google的guava缓存
	 */
	private static LoadingCache<String, Object> cache;
	static {
		cache = CacheBuilder.newBuilder().maximumSize(10000)// 设置缓存容量大小
				.expireAfterWrite(3, TimeUnit.MINUTES)// 设置缓存过期时间（3min）
				.initialCapacity(10).recordStats()// 开启统计信息开关
				.removalListener(new RemovalListener<String, Object>() {// 添加移除监听器
							@Override
							public void onRemoval(
									RemovalNotification<String, Object> rn) {
								if (logger.isInfoEnabled()) {
									System.out.printf("被移除缓存{}:{}", rn.getKey(),
											rn.getValue());
									logger.info("被移除缓存{}:{}", rn.getKey(),
											rn.getValue());
								}
							}
						}).build(new CacheLoader<String, Object>() {
					// 若缓存中有数据，则从缓存中加载数据，若缓存中没有数据，则从调用getFromDatabase()方法从数据库加载
							@Override
							public Object load(String empId) throws Exception {
								return getFromDatabase(empId);
							}

				});
	}

	/**
	 * 获取缓存
	 * 
	 * @param key
	 * @return Object
	 * @author lenovo
	 * @throws ExecutionException
	 */
	public static Object get(String key) throws ExecutionException {
		/* return StringUtils.isNotEmpty(key) ? cache.getIfPresent(key) : null; */
		return StringUtils.isNotEmpty(key) ? cache.get(key) : null;
		/* return StringUtils.isNotEmpty(key) ? cache.getUnchecked(key) : null; */
	}

	/**
	 * 放入缓存
	 * 
	 * @param key
	 * @param value
	 *            void
	 * @author lenovo
	 */
	public static void put(String key, Object value) {
		if (StringUtils.isNotEmpty(key) && value != null) {
			cache.put(key, value);
		}
	}

	/**
	 * 移除缓存
	 * 
	 * @param key
	 *            void
	 * @author lenovo
	 */
	public static void remove(String key) {
		if (StringUtils.isNotEmpty(key)) {
			cache.invalidate(key);
		}
	}

	/**
	 * 批量删除缓存
	 * 
	 * @param keys
	 *            void
	 * @author lenovo
	 */
	public static void remove(List<String> keys) {
		if (keys != null && keys.size() > 0) {
			cache.invalidateAll(keys);
		}
	}

	/**
	 * 缓存数据数量
	 * 
	 * @return Long
	 * @author lenovo
	 */
	public static Long size() {
		return cache.size();

	}

	/**
	 * 缓存的状态数据，包括(未)命中个数，加载成功/失败个数，总共加载时间，删除个数等
	 * 
	 * @return CacheStats
	 * @author lenovo
	 */
	public static CacheStats stats() {
		return cache.stats();

	}

	private static Object getFromDatabase(String empId) {
		// 模拟数据库
		Employee e1 = new Employee("Mahesh", "Finance", "100");
		Employee e2 = new Employee("Rohan", "IT", "103");
		Employee e3 = new Employee("Sohan", "Admin", "110");

		Map<String, Object> database = new HashMap<String, Object>();// 创建集合存放数据
		database.put("100", e1);// 将数据放入集合
		database.put("103", e2);
		database.put("110", e3);
		System.out.println("Database hit for" + empId);// 若数据不是从缓存中加载，则是从数据库中加载，会输出此行代码
		return database.get(empId);
	}

}
